package com.permission.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.permission.dto.request.menu.*;
import com.permission.dto.response.menu.MenuResponse;
import com.permission.entity.SysMenuEntity;
import com.permission.mapper.SysMenuMapper;
import com.permission.message.Result;
import com.permission.message.StandardResponse;
import com.permission.service.SysMenuService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限表 服务实现类
 * </p>
 *
 * @author xhs
 * @since 2021-08-27
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenuEntity> implements SysMenuService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StandardResponse<Object> insertMenu(HttpServletRequest request, InsertMenuRequest menu) {
        // 验证菜单名称是否存在
        if (menu.getParentId() != null && menu.getParentId() != 0) {
            SysMenuEntity checkoutName = getBaseMapper().selectOne(new QueryWrapper<SysMenuEntity>().lambda()
                    .eq(SysMenuEntity::getDelFlg, Constants.ZERO)
                    .eq(SysMenuEntity::getMenuName, menu.getMenuName())
                    .eq(SysMenuEntity::getParentId, menu.getParentId()));
            if (checkoutName != null) {
                return StandardResponse.error("菜单名称已存在");
            }
        }
        // 验证路由地址是否存在
        if (StringUtils.hasLength(menu.getPath())) {
            SysMenuEntity checkoutPath = getBaseMapper().selectOne(new QueryWrapper<SysMenuEntity>().lambda()
                    .eq(SysMenuEntity::getPath, menu.getPath())
                    .eq(SysMenuEntity::getParentId, menu.getParentId()));
            if (checkoutPath != null) {
                return StandardResponse.error("路由地址已存在");
            }
        }
        // 新增
        String loginId = StpUtil.getLoginIdAsString();
        menu.setCreator(loginId);
        getBaseMapper().insert(menu);
        return StandardResponse.build(Result.ADD_SUCCESS);
    }

    /**
     * 编辑菜单接口
     *
     * @param request
     * @param menuRequest
     * @return
     */
    @Override
    public StandardResponse<Object> updatetMenu(HttpServletRequest request, UpdatetMenuRequest menuRequest) {
        // 验证菜单名称是否存在
        LambdaQueryWrapper<SysMenuEntity> queryWrapper = new QueryWrapper<SysMenuEntity>().lambda()
                .eq(SysMenuEntity::getDelFlg, Constants.ZERO)
                .eq(SysMenuEntity::getParentId, menuRequest.getParentId())
                .eq(SysMenuEntity::getMenuName, menuRequest.getMenuName())
                .eq(SysMenuEntity::getMenuType, menuRequest.getMenuType())
                .ne(SysMenuEntity::getId, menuRequest.getId());

        SysMenuEntity selectOne = getBaseMapper().selectOne(queryWrapper);
        if (selectOne != null) {
            return StandardResponse.build(Result.MENU_EXIST_ERROR);
        }
        // 验证路由地址是否存在
        if (StringUtils.hasLength(menuRequest.getPath())) {
            LambdaQueryWrapper<SysMenuEntity> wrapper = new QueryWrapper<SysMenuEntity>().lambda()
                    .eq(SysMenuEntity::getDelFlg, Constants.ZERO)
                    .eq(SysMenuEntity::getParentId, menuRequest.getParentId())
                    .eq(SysMenuEntity::getPath, menuRequest.getPath())
                    .ne(SysMenuEntity::getId, menuRequest.getId());
            SysMenuEntity one = getBaseMapper().selectOne(wrapper);
            if (one != null) {
                return StandardResponse.build(Result.MENU_PATH_EXIST_ERROR);
            }
        }

        // 更新
        SysMenuEntity menuEntity = SysMenuEntity.builder()
                .id(menuRequest.getId())
                .menuName(menuRequest.getMenuName())
                .menuType(menuRequest.getMenuType())
                .orderNum(menuRequest.getOrderNum())
                .parentId(menuRequest.getParentId())
                .icon(menuRequest.getIcon())
                .path(menuRequest.getPath())
                .perms(menuRequest.getPerms())
                .build();
        boolean save = updateById(menuEntity);
        if (save) {
            return StandardResponse.build(Result.UPD_SUCCESS);
        }
        return StandardResponse.build(Result.UPD_ERROR);
    }

    /**
     * 查询菜单
     *
     * @param menuRequest
     * @return
     */
    @Override
    public StandardResponse<Object> selectMenu(SelectMenuRequest menuRequest) {
        List<SysMenuEntity> menuList = getBaseMapper().selectList(new QueryWrapper<SysMenuEntity>().lambda()
                .eq(SysMenuEntity::getDelFlg, Constants.ZERO)
                .eq(StringUtils.hasLength(menuRequest.getMenuName()), SysMenuEntity::getMenuName, menuRequest.getMenuName())
                .eq(StringUtils.hasLength(menuRequest.getMenuStatus()), SysMenuEntity::getMenuStatus, menuRequest.getMenuStatus())
                .orderByAsc(SysMenuEntity::getOrderNum));

        List<MenuResponse> menuTreeList = treeList(menuList);
        if (CollectionUtils.isEmpty(menuTreeList)) {
            return StandardResponse.build(Result.NO_DATA);
        }
        return StandardResponse.build(Result.QUERY_SUCCESS).setData(menuTreeList);
    }

    public List<MenuResponse> treeList(List<SysMenuEntity> menuList) {
        // 存放树结构的数据
        List<MenuResponse> menuTreeList = new ArrayList<>();
        if (CollectionUtils.isEmpty(menuList)) {
            return null;
        }
        // 类型转换
        List<MenuResponse> menuResponseList = copyList(menuList);
        if (CollectionUtils.isEmpty(menuResponseList)) {
            return null;
        }
        // 找到所有的一级节点存放在一个list中
        List<MenuResponse> parntList = new ArrayList<>();
        for (MenuResponse pList : menuResponseList) {
            // 父节点的pID为 0，这边按自己实际情况来判断
            if (pList.getParentId() == 0) {
                parntList.add(pList);
            }
        }
        // 为一级节点设置子节点 ,getChildren采用递归算法
        for (MenuResponse amp : parntList) {
            MenuResponse companyResponse = new MenuResponse();
            companyResponse = amp;
            companyResponse.setChildren(getChildren(amp.getId(), menuResponseList));
            menuTreeList.add(amp);
        }
        if (CollectionUtils.isEmpty(menuTreeList)) {
            return menuResponseList;
        }
        return menuTreeList;
    }

    /**
     * 递归组装树节点数据
     *
     * @param id   父节点id
     * @param list 所有数据
     * @return
     */
    public List<MenuResponse> getChildren(Integer id, List<MenuResponse> list) {
        List<MenuResponse> childrenList = new ArrayList<>();
        // 子节点
        for (MenuResponse children : list) {
            if (id.equals(children.getParentId())) {
                childrenList.add(children);
            }
        }
        // 把子节点的子节点循环一遍
        for (MenuResponse cList : childrenList) {
            cList.setChildren(getChildren(cList.getId(), list));
        }
        return childrenList;
    }

    /**
     * List泛型转换
     *
     * @param list
     * @return
     */
    private List<MenuResponse> copyList(List<SysMenuEntity> list) {
        List<MenuResponse> menuList = list.stream().map(menu -> {
            MenuResponse menuResponse = new MenuResponse();
            BeanUtils.copyProperties(menu, menuResponse);
            return menuResponse;
        }).collect(Collectors.toList());
        return menuList;
    }

    /**
     * 根据Id查询菜单数据
     *
     * @param menuRequest
     * @return
     */
    @Override
    public StandardResponse<Object> selectMenuById(SelectMenuByIdRequest menuRequest) {
        LambdaQueryWrapper<SysMenuEntity> queryWrapper = new QueryWrapper<SysMenuEntity>().lambda().eq(SysMenuEntity::getId, menuRequest.getId());
        SysMenuEntity menuEntity = getBaseMapper().selectOne(queryWrapper);
        return StandardResponse.build(Result.QUERY_SUCCESS).setData(menuEntity);
    }

    @Override
    public StandardResponse<Object> del(DelMenuRequest menuRequest) {
        LambdaQueryWrapper<SysMenuEntity> wrapper = new QueryWrapper<SysMenuEntity>().lambda()
                .eq(SysMenuEntity::getDelFlg, Constants.ZERO)
                .eq(SysMenuEntity::getId, menuRequest.getId());
        SysMenuEntity one = getBaseMapper().selectOne(wrapper);
        if (one == null) {
            return StandardResponse.build(Result.DEl_ERROR);
        }
        one.setDelFlg(1);
        boolean update = updateById(one);
        if (update) {
            return StandardResponse.build(Result.DEl_SUCCESS);
        }
        return StandardResponse.build(Result.DEl_ERROR);
    }
}
